home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Sample Code / Snippets / Development Tools & Languages / DTSCPlusLibrary / Sources / Random.cp < prev    next >
Encoding:
Text File  |  1993-01-14  |  6.7 KB  |  269 lines  |  [TEXT/MPS ]

  1. /* _________________________________________________________________________________________________________ //
  2.   Copyright © 1991-93 Apple Computer, Inc. All rights reserved.
  3.   Macintosh Developer Technical Support.C++ Macintosh Toolbox Framework.
  4.   Date: Tuesday, June 2, 1992 11:53:42
  5.   Revision comments are at the end of this file.
  6.   ---
  7.   TRandom is a stackbased utility class for random number generation.
  8.   TRandom.cp contains the member function implementations for TRandom.
  9.   _________________________________________________________________________________________________________ */
  10. // Include files
  11. #ifndef _RANDOM_
  12. #include "Random.h"
  13. #endif
  14.  
  15.  
  16. // _________________________________________________________________________________________________________ //
  17. // TRandom class member function implementations
  18. //    CONSTRUCTORS & DESTRUCTORS
  19. #pragma segment Random
  20. TRandom::TRandom(ERandType theType,
  21.                  long theSeed,
  22.                  unsigned short low,
  23.                  unsigned short high)
  24. // Default constructor, most of the parameters have default values defined in the
  25. // header file (change if needed).
  26. {
  27.     if (theSeed == 1)                            // no seed value
  28.         this->ShuffleSeed();                    // no first value, random value
  29.     else
  30.         this->SetSeedValue(theSeed);            // programmer defined seed    
  31.  
  32.     this->fLow = low;                            // define the range
  33.     this->fHigh = high;
  34.     this->fRange = high - low;
  35.  
  36.     Boolean fState = this->IRandom(theType);    // initialize the object
  37. }
  38.  
  39.  
  40. #pragma segment Random
  41. TRandom::TRandom(const TRandom& other)
  42. // copy constructor, creates clones of the TRandom class (deep copy).
  43. {
  44.     register int x;
  45.  
  46.     // fill in the needed fields with values from the referenced object
  47.     this->fGenerator = other.fGenerator;
  48.     this->fAlgorithm = other.fAlgorithm;
  49.     this->fLow = other.fLow;
  50.     this->fHigh = other.fHigh;
  51.     this->fRange = other.fRange;
  52.     this->fSeed = other.fSeed;
  53.     this->fState = other.fState;
  54.     this->fPrevNum = other.fPrevNum;
  55.  
  56.     for (x = 0; x < kSHUFFLETABLE; x++)            // copy the values from array
  57.         this->fShuffleBuf[x] = other.fShuffleBuf[x];
  58. }
  59.  
  60.  
  61. #pragma segment Random
  62. TRandom& TRandom::operator=(const TRandom& other)
  63. // assignment operator, assign a TRandom class to another for quick cloning.
  64. {
  65.     register int x;
  66.  
  67.     // fill in the needed fields with values from the referenced object
  68.     this->fGenerator = other.fGenerator;
  69.     this->fAlgorithm = other.fAlgorithm;
  70.     this->fLow = other.fLow;
  71.     this->fHigh = other.fHigh;
  72.     this->fRange = other.fRange;
  73.     this->fSeed = other.fSeed;
  74.     this->fState = other.fState;
  75.     this->fPrevNum = other.fPrevNum;
  76.  
  77.     for (x = 0; x < kSHUFFLETABLE; x++)            // copy the values from array
  78.         this->fShuffleBuf[x] = other.fShuffleBuf[x];
  79.  
  80.     return *this;
  81. }
  82.  
  83.  
  84. #pragma segment Random
  85. TRandom::~TRandom()
  86. // Virtual destructor, we are not doing anything inside this one just now, note 
  87. // that virtual destructors should not be inlined.
  88. {
  89. }
  90.  
  91.  
  92. //    INITIATION ROUTINES
  93. #pragma segment Random
  94. Boolean TRandom::IRandom(ERandType theType)
  95. // We are using a special IRandom member function for initializing class fields to
  96. // known values. This is called from both the constructor, and when we switch the
  97. // internal random number algorithm.
  98. {
  99.     switch (theType)
  100.     {
  101.         case kMACOS:
  102.             qd.randSeed = this->GetSeedValue();
  103.             this->fGenerator = &TRandom::MacRandom;// quick init
  104.             this->fAlgorithm = kMACOS;
  105.             break;
  106.         case kQUICK:
  107.             this->ShuffleSeed();
  108.             qd.randSeed = this->GetSeedValue();
  109.             this->fGenerator = &TRandom::QuickRandom;
  110.             this->fAlgorithm = kQUICK;
  111.             break;
  112.         case kSHUFFLE:
  113.             qd.randSeed = this->GetSeedValue();
  114.             this->fGenerator = &TRandom::ShuffleRandom;
  115.             this->fAlgorithm = kSHUFFLE;
  116.             this->InitShuffleRandom();
  117.             break;
  118.         case kPM:
  119.             this->fGenerator = &TRandom::ParkMiller;
  120.             this->fAlgorithm = kPM;
  121.             break;
  122.         default:
  123.             ASSERT(false, "\pProblems setting the algorithm for the random generator");
  124.             return false;                        // should never get here...
  125.     };
  126.     return true;
  127. }
  128.  
  129.  
  130. //    RANDOM GENERATOR ALGORITHMS/MEMBER FUNCTIONS
  131. #pragma segment Random
  132. unsigned short TRandom::MacRandom()
  133. // Macintosh Toolbox random number generator.
  134. {
  135.     register unsigned short temp;
  136.  
  137.     temp =
  138.           short(::Random());                    // scale to  0 - 65536
  139.     return (((temp * this->fRange) / k16BIT) + this->fLow);
  140. }
  141.  
  142.  
  143. #pragma segment Random
  144. unsigned short TRandom::QuickRandom()
  145. // quick asm random generator, calls AsmRandom which is implemented in assembly.
  146. {
  147.     register unsigned short temp;
  148.  
  149.     temp =
  150.           short(AsmRandom());                    // scale to  0 - 65536
  151.     return (((temp * this->fRange) / k16BIT) + this->fLow);
  152. }
  153.  
  154.  
  155. #pragma segment Random
  156. unsigned short TRandom::ShuffleRandom()
  157. // Shuffle Random algorithm, uses an internal table for shuffling values for more
  158. // random distribution
  159. {
  160.     register unsigned short index;
  161.  
  162.     index = (this->fPrevNum * kSHUFFLETABLE) / k16BIT;
  163.     this->fPrevNum = this->fShuffleBuf[index];    // get random number from table
  164.     this->fShuffleBuf[index] = Random();        // new random table entry
  165.  
  166.     return (((this->fPrevNum * this->fRange) / k16BIT) + this->fLow);
  167. }
  168.  
  169.  
  170. #pragma segment Random
  171. TRandom& TRandom::InitShuffleRandom()
  172. // Used to initialize the Shuffle random algorithm
  173. {
  174.     register short i;
  175.  
  176.     for (i = 0; i < kSHUFFLETABLE; i++)
  177.         Random();                                // shuffle the random generator
  178.     for (i = 0; i < kSHUFFLETABLE; i++)
  179.         this->fShuffleBuf[i] = Random();        // fill the buffer
  180.  
  181.     this->fPrevNum = Random();                    // get first 'later' value
  182.     return *this;
  183. }
  184.  
  185.  
  186. #pragma segment Random
  187. unsigned short TRandom::ParkMiller()
  188. // CACM Oct 1988 Park& Miller algorithm.
  189. {
  190.     unsigned short high,
  191.      low;
  192.     register unsigned short temp;
  193.  
  194.     high =
  195.           short(this-> fSeed/ kPM3);
  196.     low =
  197.          short(this-> fSeed% kPM3);
  198.     temp = (kPM2 * low) - (kPM1 * high);
  199.  
  200.     if (temp > 0)
  201.         this->fSeed = temp;
  202.     else
  203.         this->fSeed = temp + kACM_MAX;
  204.  
  205.     return (((temp * this->fRange) / k16BIT) + this->fLow);
  206. }
  207.  
  208.  
  209. #pragma segment Random
  210. unsigned short TRandom::Next()
  211. // Iterate to next value.
  212. {
  213.     return (this->*fGenerator)();
  214. }
  215.  
  216.  
  217. #pragma segment Random
  218. TRandom& TRandom::ShuffleSeed()
  219. // Shuffle the current seed.
  220. {
  221.     this->fSeed = TickCount();
  222.     return *this;
  223. }
  224.  
  225.  
  226. // GET/SET FUNCTIONS
  227. #pragma segment Random
  228. TRandom& TRandom::SetRandomGenerator(TRandom::ERandType theType)
  229. // Select the random generator algorithm.
  230. {
  231.     this->IRandom(theType);
  232.     return *this;
  233. }
  234.  
  235.  
  236. #pragma segment Random
  237. long TRandom::GetSeedValue() const
  238. // Return current seed value.
  239. {
  240.     return this->fSeed;
  241. }
  242.  
  243.  
  244. #pragma segment Random
  245. TRandom& TRandom::SetSeedValue(const long theSeed)
  246. // Set current seed value
  247. {
  248.     this->fSeed = theSeed;
  249.     qd.randSeed = theSeed;
  250.     return *this;
  251. }
  252.  
  253.  
  254. #pragma segment Random
  255. TRandom::ERandType TRandom::GetAlgorithmType() const
  256. // Return algorithm type.
  257. {
  258.     return this->fAlgorithm;
  259. }
  260.  
  261.  
  262. // _________________________________________________________________________________________________________ //
  263.  
  264. /*    Change History (most recent last):
  265.   No        Init.    Date        Comment
  266.   1            khs        6/2/92        New file
  267.   2            khs        1/7/93        Cleanup
  268. */
  269.